﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Xml.Linq;
//
namespace PerceptiveMCAPI.Types
{
   public class campaignEepUrlStatsOutput : Api_BaseOutput
   {
      public campaignEepUrlStatsResults result { get; set; }
      public campaignEepUrlStatsParms inputParms { get; private set; }
      //
      public campaignEepUrlStatsOutput( campaignEepUrlStatsInput input )
         : base( input )
      {
         inputParms = input.parms;
         result = new campaignEepUrlStatsResults();
      }
      // --------------------------------------------------- tostring
      public override string ToString()
      {
         return string.Format( "Tweets: {0}", this.result );
      }

      #region ================================================================== format setup

      // ---- serial
      internal void Format( string api_Request, string api_Response )
      {
         this.api_Request = api_Request;
         this.api_Response = api_Response;
         // ----------------------------------
         if ( this.api_OutputType == EnumValues.OutputType.JSON )
            outputJSON();
         else if ( this.api_OutputType == EnumValues.OutputType.XML )
            outputXML();
      }

      // ---- xmlrpc
      internal void Format( object rpcResult )
      {
         this.api_Request = EnumValues.NotSupplied;
         this.api_Response = EnumValues.NotSupplied;
         // ------------------------
         this.result = FormatResults( rpcResult );
      }

      #endregion

      #region ================================================================= Output

      // ---------------------------------------------------------- outputXML
      private void outputXML()
      {
         XElement xml = XElement.Parse( this.api_Response );
         // error check
         Api_Error error = apiSerial.GetXmlOutputError( xml );
         if ( error != null )
         {
            this.api_ErrorMessages.Add( error );
            return;
         }
         // -------------------------------------------- get values
         try
         {
            if ( xml.HasElements )
            {
               campaignEepUrlStatsResults results = new campaignEepUrlStatsResults();
               DateTime dt; int it;
               // ------------------------------------------------------------------------------- twitter section
               XElement twitter = xml.Element( "twitter" );
               if ( twitter != null && twitter.HasElements )
               {
                  campaignEepUrlStatsResults.twitter rTwitter = new campaignEepUrlStatsResults.twitter();
                  //
                  int.TryParse( twitter.Element( "tweets" ).Value, out it );
                  rTwitter.tweets = it;
                  DateTime.TryParse( twitter.Element( "first_tweet" ).Value, out dt );
                  rTwitter.first_tweet = dt;
                  DateTime.TryParse( twitter.Element( "last_tweet" ).Value, out dt );
                  rTwitter.last_tweet = dt;
                  //                
                  int.TryParse( twitter.Element( "retweets" ).Value, out it );
                  rTwitter.retweets = it;
                  DateTime.TryParse( twitter.Element( "first_retweet" ).Value, out dt );
                  rTwitter.first_retweet = dt;
                  DateTime.TryParse( twitter.Element( "last_retweet" ).Value, out dt );
                  rTwitter.last_retweet = dt;
                  //
                  XElement twitStatus = twitter.Element( "statuses" );
                  if ( twitStatus.HasElements )
                  {
                     IEnumerable<XElement> statuses = twitStatus.Descendants( "struct" );
                     foreach ( XElement sts in statuses )
                     {
                        campaignEepUrlStatsResults.twitter.tweet_status tweet = new campaignEepUrlStatsResults.twitter.tweet_status();
                        tweet.status = sts.Element( "status" ).Value;
                        tweet.screen_name = sts.Element( "screen_name" ).Value;
                        tweet.status_id = sts.Element( "status_id" ).Value;
                        DateTime.TryParse( sts.Element( "datetime" ).Value, out dt );
                        tweet.datetime = dt;
                        tweet.is_retweet = ( sts.Element( "is_retweet" ).Value == "1" ) ? true : false;
                        //
                        rTwitter.statuses.Add( tweet );
                     }
                  }
                  //
                  results.Twitter = rTwitter;
                  // ------------------------------------------------------------------------------- clicks section

                  XElement click = xml.Element( "click" );
                  if ( click != null && click.HasElements )
                  {
                     campaignEepUrlStatsResults.click rClick = new campaignEepUrlStatsResults.click();
                     //
                     int.TryParse( click.Element( "clicks" ).Value, out it );
                     rClick.clicks = it;
                     DateTime.TryParse( click.Element( "first_click" ).Value, out dt );
                     rClick.first_click = dt;
                     DateTime.TryParse( click.Element( "last_click" ).Value, out dt );
                     rClick.last_click = dt;
                     //                
                     XElement clickLocations = click.Element( "locations" );
                     if ( clickLocations != null && clickLocations.HasElements )
                     {
                        IEnumerable<XElement> locations = clickLocations.Descendants( "struct" );
                        foreach ( XElement loc in locations )
                        {
                           campaignEepUrlStatsResults.click.location location = new campaignEepUrlStatsResults.click.location();
                           location.country = loc.Element( "country" ).Value ?? "";
                           location.region = loc.Element( "region" ).Value ?? "";
                           int.TryParse( loc.Element( "clicks" ).Value, out it );
                           location.clicks = it;
                           //
                           rClick.locations.Add( location );
                        }
                     }
                     //
                     results.Click = rClick;
                  }

                  // ------------------------------------------------------------------------------- referrals section
                  XElement referral_section = xml.Element( "referrers" );
                  if ( referral_section != null && referral_section.HasElements )
                  {
                     List<campaignEepUrlStatsResults.referrers> referrers = new List<campaignEepUrlStatsResults.referrers>();
                     //
                     IEnumerable<XElement> refer_list = referral_section.Descendants( "struct" );
                     foreach ( var refer in refer_list )
                     {
                        var entry = new campaignEepUrlStatsResults.referrers();
                        entry.referrer = refer.Element( "referrer" ).Value;
                        int.TryParse( refer.Element( "clicks" ).Value, out it );
                        entry.clicks = it;
                        DateTime.TryParse( refer.Element( "first_click" ).Value, out dt );
                        entry.first_click = dt;
                        DateTime.TryParse( refer.Element( "last_click" ).Value, out dt );
                        entry.last_click = dt;
                        //
                        referrers.Add( entry );
                     }
                     //
                     results.Referrers = referrers;
                  }
                  //=============================
                  this.result = results;
               }
            }
         }
         catch ( Exception ex )
         {
            this.api_ErrorMessages.Add( apiException.FormatError( ex ) );
         }
      }

      // ---------------------------------------------------------- outputJSON
      private void outputJSON()
      {
         JavaScriptSerializer jss = new JavaScriptSerializer();
         try
         {
            if ( this.api_Response.Contains( EnumValues.JSONErrorString ) )
            {
               Api_Error err = jss.Deserialize<Api_Error>( this.api_Response );
               this.api_ErrorMessages.Add( err );
            }
            else
            {
               object JSONResult = jss.Deserialize<object>( this.api_Response );
               this.result = FormatResults( JSONResult );
            }
         }
         catch ( Exception ex )
         {
            this.api_ErrorMessages.Add( apiException.FormatError( ex ) );
         }
      }

      // ---------------------------------------------------------------------- Format results
      private campaignEepUrlStatsResults FormatResults( object x_results )
      {
         // ********************************************************
         campaignEepUrlStatsResults results = new campaignEepUrlStatsResults();
         DateTime dt; int it;
         //
         // ------------------------ grab 'em
         //
         if ( x_results == null ) return results;    // no results
         //
         IDictionary xdict = x_results as IDictionary;
         IDictionary iTwitter = xdict["twitter"] as IDictionary;
         IDictionary iClick = xdict["click"] as IDictionary;
         object[] oReferrers = xdict["referrers"] as object[];
         // ------------------------------------------------------------------- twitter
         if ( iTwitter != null && iTwitter.Count > 0 )
         {
            results.Twitter.tweets = int.Parse( iTwitter["tweets"].ToString() );
            DateTime.TryParse( iTwitter["first_tweet"].ToString(), out dt );
            results.Twitter.first_tweet = dt;
            DateTime.TryParse( iTwitter["last_tweet"].ToString(), out dt );
            results.Twitter.last_tweet = dt;
            results.Twitter.retweets = int.Parse( iTwitter["retweets"].ToString() );
            DateTime.TryParse( iTwitter["first_retweet"].ToString(), out dt );
            results.Twitter.first_retweet = dt;
            DateTime.TryParse( iTwitter["last_retweet"].ToString(), out dt );
            results.Twitter.last_retweet = dt;
            //
            results.Twitter.statuses = FormatStatuses( iTwitter["statuses"] );
         }
         // ------------------------------------------------------------------- click
         if ( iClick != null && iClick.Count > 0 )
         {
            results.Click.clicks = int.Parse( iClick["clicks"].ToString() );
            DateTime.TryParse( iClick["first_click"].ToString(), out dt );
            results.Click.first_click = dt;
            DateTime.TryParse( iClick["last_click"].ToString(), out dt );
            results.Click.last_click = dt;
            results.Click.locations = FormatLocations( iClick["locations"] );
         }
         // ------------------------------------------------------------------- referrers
         if ( oReferrers != null && oReferrers.Length > 0 )
         {
            List<campaignEepUrlStatsResults.referrers> refList = new List<campaignEepUrlStatsResults.referrers>();
            foreach ( var item in oReferrers )
            {
               IDictionary rDict = item as IDictionary;
               campaignEepUrlStatsResults.referrers entry = new campaignEepUrlStatsResults.referrers();
               //
               entry.referrer = rDict["referrer"].ToString();
               int.TryParse( rDict["clicks"].ToString(), out it );
               entry.clicks = it;
               DateTime.TryParse( rDict["first_click"].ToString(), out dt );
               entry.first_click = dt;
               DateTime.TryParse( rDict["last_click"].ToString(), out dt );
               entry.last_click = dt;
               //
               refList.Add( entry );
            }
            results.Referrers = refList;
         }
         // ---------------------------
         return results;
      }

      // --------------------------------------------------
      private List<campaignEepUrlStatsResults.twitter.tweet_status> FormatStatuses( object status_entries )
      {
         List<campaignEepUrlStatsResults.twitter.tweet_status> tweets = new List<campaignEepUrlStatsResults.twitter.tweet_status>();
         object[] statuses = status_entries as object[];
         //
         IEnumerator de = statuses.GetEnumerator();
         while ( de.MoveNext() )
         {
            IDictionary tweet_obj = de.Current as IDictionary;
            DateTime dt;
            campaignEepUrlStatsResults.twitter.tweet_status tweet = new campaignEepUrlStatsResults.twitter.tweet_status();

            tweet.status = tweet_obj["status"].ToString();
            tweet.screen_name = tweet_obj["screen_name"].ToString();
            tweet.status_id = tweet_obj["status_id"].ToString();
            DateTime.TryParse( tweet_obj["datetime"].ToString(), out dt );
            tweet.datetime = dt;
            tweet.is_retweet = ( tweet_obj["is_retweet"].ToString() == "1" ) ? true : false;
            //
            tweets.Add( tweet );
         }
         //
         return tweets;
      }

      private List<campaignEepUrlStatsResults.click.location> FormatLocations( object location_entries )
      {
         List<campaignEepUrlStatsResults.click.location> locations = new List<campaignEepUrlStatsResults.click.location>();
         object[] locs = location_entries as object[];
         // 
         IEnumerator de = locs.GetEnumerator();
         int it;
         while ( de.MoveNext() )
         {
            IDictionary loc_obj = de.Current as IDictionary;
            campaignEepUrlStatsResults.click.location loc = new campaignEepUrlStatsResults.click.location();
            loc.country = loc_obj["country"].ToString() ?? "";
            loc.region = loc_obj["region"].ToString() ?? "";
            int.TryParse( loc_obj["clicks"].ToString(), out it );
            loc.clicks = it;
            //
            locations.Add( loc );
         }
         return locations;
      }
      // --------------------------------------------------

      #endregion
   }
}
